package com.hzncc.flowable_diboot.service.report.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.data.*;
import com.deepoove.poi.policy.DynamicTableRenderPolicy;
import com.deepoove.poi.policy.TableRenderPolicy;
import com.deepoove.poi.util.TableTools;
import com.diboot.core.util.BeanUtils;
import com.diboot.core.util.SqlExecutor;
import com.diboot.core.vo.JsonResult;
import com.diboot.file.util.FileHelper;
import com.diboot.iam.service.SystemConfigService;
import com.hzncc.flowable_diboot.service.DingtalkService;
import com.hzncc.flowable_diboot.util.ConstantUtil;
import com.hzncc.flowable_diboot.util.WordUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSpacing;
import org.springframework.stereotype.Service;

import com.diboot.core.util.S;
import com.diboot.core.service.impl.BaseServiceImpl;

import com.hzncc.flowable_diboot.entity.report.WeeklySummaryReport;

import com.hzncc.flowable_diboot.mapper.report.WeeklySummaryReportMapper;
import com.hzncc.flowable_diboot.service.report.WeeklySummaryReportService;

import java.io.FileOutputStream;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 周报报表 相关Service实现类
 *
 * @author MyName
 * @version 1.0
 * @date 2024-11-25
 * Copyright © MyCorp
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class WeeklySummaryReportServiceImpl extends BaseServiceImpl<WeeklySummaryReportMapper, WeeklySummaryReport> implements WeeklySummaryReportService {

    private final DingtalkService dingtalkService;

    @Override
    public void sendWeeklyReportFile(Map<String, Object> param) throws Exception {
        // 获取各分公司周报接收人
        List<Map<String, Object>> maps = SqlExecutor.executeQuery(S.format("select prop_key,prop_value,tenant_id from dbt_system_config where prop_key = '{}' and is_deleted = 0", ConstantUtil.WEEKLY_REPORT_RECIPIENT));
        Map<String, Set<String>> userMap = new HashMap<>();
        for (Map<String, Object> m : maps) {
            String propValue = StrUtil.toStringOrNull(m.get("prop_value"));
            if (propValue == null) {
                continue;
            }
            String[] userNums = propValue.split(",");
            for (String userNum : userNums) {
                if (userMap.containsKey(userNum)) {
                    userMap.get(userNum).add(StrUtil.toStringOrNull(m.get("tenant_id")));
                } else {
                    userMap.put(userNum, new HashSet<>(Collections.singletonList(StrUtil.toStringOrNull(m.get("tenant_id")))));
                }
            }
        }
        // 以接收人维度整理周报数据
        int week = DateUtil.weekOfYear(new Date());
        Object currentWeek = param.get("currentWeek");
        // currentWeek为0，表示上周
        if (S.equals(StrUtil.toStringOrNull(currentWeek), "0")) {
            week = week - 1;
        }
        List<Map<String, Object>> report = SqlExecutor.executeQuery(S.format("select * from mdl_weekly_summary_report where week = {} and is_deleted = 0 order by tenant_id,customer_id", week));
        List<WeeklySummaryReport> weeklySummaryReports = new ArrayList<>();
        for (Map<String, Object> map : report) {
            WeeklySummaryReport val = new WeeklySummaryReport();
            val.setContent(StrUtil.toStringOrNull(map.get("content")));
            val.setTenantName(StrUtil.toStringOrNull(map.get("tenant_name")));
            val.setCustomerName(StrUtil.toStringOrNull(map.get("customer_name")));
            val.setTenantId(StrUtil.toStringOrNull(map.get("tenant_id")));
            val.setCustomerId(StrUtil.toStringOrNull(map.get("customer_id")));
            val.setRemark(StrUtil.toStringOrNull(map.get("remark")));
            val.setEditMembers(StrUtil.toStringOrNull(map.get("edit_members")));
            //val.setMondayDate(LocalDateTimeUtil.of((Date) map.get("monday_date")) != null ? LocalDateTimeUtil.of((Date) map.get("monday_date")).toLocalDate() : null);
            val.setWeek(Integer.parseInt(StrUtil.toStringOrNull(map.get("week"))));
            weeklySummaryReports.add(val);
        }
        Map<String, Map<String, Object>> templateParamGroupByUser = new HashMap<>();
        for (Map.Entry<String, Set<String>> entry : userMap.entrySet()) {
            Set<String> tenantSet = entry.getValue();
            List<WeeklySummaryReport> weekReport = weeklySummaryReports.stream().filter(e -> tenantSet.contains(e.getTenantId())).toList();
            Map<String, Object> templateParam = new HashMap<>();
            templateParam.put("start", DateUtil.beginOfWeek(new Date()).toString("yyyy-MM-dd"));
            templateParam.put("end", DateUtil.endOfWeek(new Date()).toString("yyyy-MM-dd"));
            templateParam.put("detail_table", weekReport);
            templateParamGroupByUser.put(entry.getKey(), templateParam);
        }
        // 生成周报文件
        // 1. 获取模板文件
        String resourceFilePath = WordUtils.getResourceFilePath("word/weekly-report.docx");
        // 2. 获取系统临时文件夹
        String systemTempDir = FileHelper.getSystemTempDir().replaceAll("\\\\", "/");
        if (!systemTempDir.endsWith("/")) {
            systemTempDir += "/";
        }
        // 3. 生成文件
        Configure config = Configure.builder().bind("detail_table", new DynamicTableRenderPolicy() {

            final int startRow = 1;

            @Override
            public void render(XWPFTable xwpfTable, Object o) throws Exception {
                List<WeeklySummaryReport> items = (List<WeeklySummaryReport>) o;
                if (!items.isEmpty()) {
                    // 移除空行
                    xwpfTable.removeRow(startRow);
                    Map<String, int[]> rowSpanMap = new HashMap<>();
                    // 循环插入行
                    for (int i = 0; i < items.size(); i++) {
                        XWPFTableRow insertNewTableRow = xwpfTable.insertNewTableRow(startRow);
                        for (int j = 0; j < 4; j++) insertNewTableRow.createCell();
                        // 单行渲染
                        RowRenderData renderData = Rows.of(items.get(i).getTenantName(), items.get(i).getCustomerName(),
                                items.get(i).getContent(), items.get(i).getRemark()).create();
                        // 记录需要合并的行数
                        if (rowSpanMap.containsKey(items.get(i).getTenantId())) {
                            int[] rowSpan = rowSpanMap.get(items.get(i).getTenantId());
                            // 结束行累加
                            rowSpan[1]++;
                            rowSpanMap.put(items.get(i).getTenantId(), rowSpan);
                        } else {
                            rowSpanMap.put(items.get(i).getTenantId(), new int[]{i + startRow, i + startRow});
                        }
                        TableRenderPolicy.Helper.renderRow(xwpfTable.getRow(1), renderData);
                    }
                    // 合并单元格
                    for (Map.Entry<String, int[]> entry : rowSpanMap.entrySet()) {
                        TableTools.mergeCellsVertically(xwpfTable, 0, entry.getValue()[0], entry.getValue()[1]);
                    }
                    List<XWPFTableRow> rows = xwpfTable.getRows();
                    for (XWPFTableRow row : rows) {
                        XWPFTableCell cell = row.getCell(0);
                        cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
                        XWPFParagraph paragraph = cell.getParagraphArray(0);
                        paragraph.setAlignment(ParagraphAlignment.CENTER);
                        XWPFRun run = paragraph.getRuns().get(0);
                        run.setBold(true);
                        for (int i = 0; i < 4; i++) {
                            XWPFTableCell tableCell = row.getCell(i);
                            XWPFParagraph cellParagraph = tableCell.getParagraphArray(0);
                            XWPFRun cellRun = cellParagraph.getRuns().get(0);
                            cellRun.setFontSize(12);
                            cellParagraph.setSpacingBetween(1.5, LineSpacingRule.AUTO); // 1.5倍行间距
                        }
                    }
                }
            }
        }).build();
        Map<String, String> filePathMap = new HashMap<>();
        for (Map.Entry<String, Map<String, Object>> en : templateParamGroupByUser.entrySet()) {
            String filePath = systemTempDir + "周报" + LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + ".docx";
            try (XWPFTemplate template = XWPFTemplate.compile(resourceFilePath, config).render(en.getValue())) {
                template.writeToFile(filePath);
                filePathMap.put(en.getKey(), filePath);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        // 上传文件并发送钉钉工作通知
        JsonResult<String> token = dingtalkService.getToken();
        if (token.getCode() == 0) {
            for (Map.Entry<String, String> entry : filePathMap.entrySet()) {
                JsonResult<String> file = dingtalkService.uploadFile(token.getData(), entry.getValue(), "file");
                if (file.getCode() == 0) {
                    Map<String, Object> msgParam = new HashMap<>();
                    msgParam.put("msgtype", "file");
                    msgParam.put("media_id", file.getData());
//                    msgParam.put("fileName", entry.getValue().substring(entry.getValue().lastIndexOf('/') + 1));
                    JsonResult<String> msgKey = dingtalkService.sendWorkNotice(token.getData(), entry.getKey(), msgParam);
                    // todo 钉钉消息发送失败处理
                    if (msgKey.getCode() != 0) {
                        log.error("发送钉钉工作通知失败:" + msgKey.getMsg());
                    }
                }
            }
        }
    }
}